package presenter;

import java.awt.*;
import java.awt.event.*;
import java.io.File;
import javax.swing.*;


public class MainWindow extends JFrame implements WindowListener, ActionListener, KeyListener, MouseListener {
    private VideoFrame vf0;
    private VideoFrame vf1;
    private Bible bible;
    private JPanel jdp;
    private JPanel split;
    SongChooser sc;
    Scheduler scheduler;
    SongDisplayer sd0;
    SongDisplayer sd1;
    private SimpleVariableFile fp;
    private SimpleVariableFile songs;
    
    Component[] components;
    
    private TextOutput out;
    private int width;
    private int height;
    private JToggleButton clear;
    private JToggleButton black;
    private Finder finder;
    private AdvancedSchedulerDialog as;
    private SongEditor editor;
    private boolean source;
    private AdvancedScheduler defaultEditor;
    private Preferences preferences;
    private JMenu options;
    private JMenuItem prefs;
    File background;
    Timer t;
    private Component videoControls;
    SongFile defaultSong;
    JMenuBar menuBar;
    JMenu fileMenu;
    JMenuItem open;
    JMenuItem save;
    JMenuItem close;
    JPanel split1;
    JMenuItem advancedSchedule;
    JMenu song;
    JMenuItem newSong;
    JMenuItem editSong;
    JMenuItem editDefault;
    JMenuItem findSong;
    Node<Component> selected;
    
    public MainWindow() {
        this(800, 600);
    }

    public MainWindow(int width, int height) {
        this(width, height, "./MediaData.txt");
    }

    public MainWindow(int width, int height, String media) {
        this(width, height, media, "./FramePositions.txt");
    }

    public MainWindow(int width, int height, String media, String framepos) {
        super("Easy Media Presenter");
        File songDB = new File(media);
        if(!songDB.isFile()) {
            JFileChooser chooser = new JFileChooser();
            int returnVal = chooser.showOpenDialog(null);
            if(returnVal == 0)
                songDB = chooser.getSelectedFile();
        }
        
        songs = new SimpleVariableFile(songDB);
        try {
            BibleInformation.defaultBible=songs.getVariable("DefaultBible");
            bible = BibleInformation.getDefaultBible();//new Bible(new File("Bibles/"+songs.getVariable("DefaultBible")),songs.getVariable("DefaultBible"));
            
        } catch(Exception e) { }
        setIconImage(Toolkit.getDefaultToolkit().getImage("emp.png"));
        source = true;
        this.width = width;
        this.height = height;
        addWindowListener(this);
        jdp = new JPanel(new BorderLayout());
        split = new JPanel(new GridLayout(2, 1));
        
        File f = new File("Songs");
        background = new File(songs.getVariable("Background"));
        defaultSong = new SongFile("Default");
        defaultSong.setBackground(songs.getVariable("Background"));
        String colors = songs.getVariable("FontColor");
        int red = Integer.parseInt(colors.substring(1, colors.indexOf('G')));
        int green = Integer.parseInt(colors.substring(colors.indexOf('G') + 1, colors.indexOf('B')));
        int blue = Integer.parseInt(colors.substring(colors.indexOf('B') + 1, colors.length()));
        Color color = new Color(red, green, blue);
        defaultSong.setColor(color);
        sc = new SongChooser(f,bible);
        scheduler = new Scheduler(null, sc.getSongs(),bible);
        sc.getBibleChooser().setScheduler(scheduler);
        sd0 = new SongDisplayer(defaultSong);
        sd1 = new SongDisplayer(null);
        
        Component[] components ={sc,scheduler,sd0,sd1};
        /*for(int i=0; i<components.length; i++) {
            components[i].addKeyListener(this);
        }*/
        sc.addKeyListener(this);

        scheduler.addKeyListener(this);
        sd0.addKeyListener(this);
        sd1.addKeyListener(this);
        selected=new Node<Component>();
        selected.createCircularList(components);
        
        out = new TextOutput();
        out.setDefaultSong(defaultSong);
        initComponents(framepos);
        
       
        t = new Timer(40, this);
        t.start();
        split.add(scheduler);
        split.add(sc);
        jdp.add(split, BorderLayout.WEST);
        split1 = new JPanel(new GridLayout(1, 2));
        split1.add(sd0);
        split1.add(sd1);
        jdp.add(split1, BorderLayout.CENTER);
        jdp.setSize(width, height);
        jdp.setVisible(true);
        menuBar = new JMenuBar();
        fileMenu = new JMenu("File");
        open = new JMenuItem("Open Schedule");
        open.setAccelerator(KeyStroke.getKeyStroke(79, 2));
        save = new JMenuItem("Save Schedule");
        save.setAccelerator(KeyStroke.getKeyStroke(83, 2));
        close = new JMenuItem("Close");
        save.addActionListener(this);
        open.addActionListener(this);
        close.addActionListener(this);
        advancedSchedule = new JMenuItem("Edit Schedule");
        advancedSchedule.setAccelerator(KeyStroke.getKeyStroke(87, 2));
        fileMenu.add(advancedSchedule);
        advancedSchedule.addActionListener(this);
        menuBar.add(fileMenu);
        song = new JMenu("Song");
        newSong = new JMenuItem("New Song");
        newSong.addActionListener(this);
        newSong.setAccelerator(KeyStroke.getKeyStroke(78, 2));
        editSong = new JMenuItem("Edit Song");
        editSong.addActionListener(this);
        editSong.setAccelerator(KeyStroke.getKeyStroke(69, 2));
        findSong = new JMenuItem("Find Song");
        findSong.addActionListener(this);
        findSong.setAccelerator(KeyStroke.getKeyStroke(70, 2));
        editDefault = new JMenuItem("Edit Output Defaults");
        editDefault.addActionListener(this);
        editDefault.setAccelerator(KeyStroke.getKeyStroke(68, 2));
        song.add(newSong);
        song.add(editSong);
        song.add(findSong);
        song.add(editDefault);
        menuBar.add(song);
        options = new JMenu("Options");
        prefs = new JMenuItem("Preferences");
        prefs.addActionListener(this);
        prefs.setAccelerator(KeyStroke.getKeyStroke(80, 2));
        options.add(prefs);
        menuBar.add(options);
        clear = new JToggleButton("Clear", null);
        black = new JToggleButton("Black", null);
        menuBar.add(Box.createHorizontalGlue());
        menuBar.add(clear);
        clear.addActionListener(this);
        menuBar.add(black);
        black.addActionListener(this);
        fileMenu.add(open);
        fileMenu.add(save);
        fileMenu.add(close);
        setJMenuBar(menuBar);
        getContentPane().add(jdp);
        setDefaultCloseOperation(2);
        setVisible(true);
        sc.requestFocusInWindow();
        
        //requestFocus();
    }

    public void updatePositions() {
        if(fp == null) {
            return;
        } else {
            fp.update("OutputX", (new StringBuilder()).append("").append(out.getX()).toString());
            fp.update("OutputY", (new StringBuilder()).append("").append(out.getY()).toString());
            fp.update("OutputWidth", (new StringBuilder()).append("").append(out.getWidth()).toString());
            fp.update("OutputHeight", (new StringBuilder()).append("").append(out.getHeight()).toString());
            fp.write();
            return;
        }
    }

    public void setSize(String f) {
        SimpleVariableFile svf = new SimpleVariableFile(new File(f));
        if(svf.exists("MainWindowWidth") && svf.exists("MainWindowHeight")) {
            int width = Integer.parseInt(svf.getVariable("MainWindowWidth"));
            int height = Integer.parseInt(svf.getVariable("MainWindowHeight"));
            setSize(width, height);
        }
    }

    public void setIcon(String path)
    {
        setIconImage(Toolkit.getDefaultToolkit().getImage(path));
    }

    public void initComponents(String framepos) {
        sc.setVisible(true);
        scheduler.setVisible(true);
        sd0.setVisible(true);
        
        File pos = new File(framepos);
        if(!pos.isFile()) {
            try {
                pos = new File("MonitorData.txt");
                ScreenDetector sd = new ScreenDetector();
                if(pos.isFile()) {
                    SimpleVariableFile positions = new SimpleVariableFile(pos);
                    //System.out.println((new StringBuilder()).append(positions.getVariable("MainMonitor")).append(" ").append(positions.exists("MainMonitor")).toString());
                    if(positions.exists("MainMonitor") && positions.getVariable("MainMonitor").equals("1")) {
                        //System.out.println("setting to secondary monitor");
                        setBounds(sd.getSecondDisplayBounds());
                    } else {
                        setBounds(sd.getFirstDisplayBounds());
                    }
                    if(sd.getSecondDisplayBounds()==null) {
                        out.getFrame().setVisible(false);
                        out.getFrame().setUndecorated(false);
                        out.getFrame().setVisible(true);
                        //System.out.println("giving output screen window decoration");
                        out.setBounds(sd.getFirstDisplayBounds());

                        setBounds(sd.getFirstDisplayBounds());
                    }
                    else if(positions.exists("OutputMonitor") && positions.getVariable("OutputMonitor").equals("1")) {
                        out.setLocation(0, 0);
                        out.setBounds(sd.getSecondDisplayBounds());
                        //out.changeSize((int)sd.getSecondDisplayBounds().getWidth(), (int)sd.getSecondDisplayBounds().getHeight());
                    } else {
                        //System.out.println((new StringBuilder()).append("setting output to first monitor ").append(sd.getFirstDisplayBounds()).toString());
                        out.setBounds(sd.getFirstDisplayBounds());
                        out.changeSize((int)sd.getFirstDisplayBounds().getWidth(), (int)sd.getFirstDisplayBounds().getHeight());
                    }
                } else if(sd.getSecondDisplayBounds() != null) {
                    out.setBounds(sd.getSecondDisplayBounds());
                    out.changeSize((int)sd.getSecondDisplayBounds().getWidth(), (int)sd.getSecondDisplayBounds().getHeight());
                    setBounds(sd.getFirstDisplayBounds());
                    //System.out.println((new StringBuilder()).append("second screen detected ").append(sd.getSecondDisplayBounds()).toString());
                } else {
                    out.getFrame().setVisible(false);
                    out.getFrame().setUndecorated(false);
                    out.getFrame().setVisible(true);
                    //System.out.println("giving output screen window decoration");
                    out.setBounds(sd.getFirstDisplayBounds());
                    
                    setBounds(sd.getFirstDisplayBounds());
                }
                out.getFrame().setVisible(true);
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        } else  {
            fp = new SimpleVariableFile(pos);
            int x = Integer.parseInt(fp.getVariable("OutputX"));
            int y = Integer.parseInt(fp.getVariable("OutputY"));
            int width = Integer.parseInt(fp.getVariable("OutputWidth"));
            int height = Integer.parseInt(fp.getVariable("OutputHeight"));
            out.changeLocation(x, y);
            out.changeSize(width, height);
            out.setVisible(true);
        }
        setExtendedState(MAXIMIZED_BOTH);
        out.getFrame().setExtendedState(MAXIMIZED_BOTH);
    }

    public void setSchedule(File f) {
        scheduler.setSchedule(f, sc.getSongs(), bible);
    }

    public void windowOpened(WindowEvent windowevent) {
    }

    public void windowClosing(WindowEvent e)
    {
        if(preferences != null && e.getSource() == preferences) {
            out.changeLocation(preferences.getX(), preferences.getY());
            out.changeSize(preferences.getOutputWidth(), preferences.getOutputHeight());
            out.setFont(preferences.getFontName());
        }
        if(editor != null && e.getSource() == editor.getFrame()) {
            System.out.println("editor changed");
            if(source)
            {
                if(sd0.getSong().getNumber() == editor.getSong().getNumber()&&sd0.getSong().getNumber()!=0) {
                    sd0.setActive(0);
                    sd0.setSong(editor.getSong());
                }
            } else if(sd1.getSong().getNumber() == editor.getSong().getNumber()&&sd1.getSong().getNumber()!=0) {
                sd1.setActive(0);
                sd1.setSong(editor.getSong());
            }
            if(!sc.exists(editor.getSong().getNumber())&&editor.getSong().getNumber()!=0) {
                System.out.println("adding new Song "+editor.getSong().getNumber());
                if(editor.getSong().getFile()!=null)
                sc.addSong(editor.getSong());
            }
            //for(int i=0; i<)
        } else if(defaultEditor != null && e.getSource() == defaultEditor) {
            out.setDefaultSong(defaultSong);
            songs.update("Background", defaultSong.getBackground());
            String fontColor = (new StringBuilder()).append("R").append(defaultSong.getColor().getRed()).toString();
            fontColor = (new StringBuilder()).append(fontColor).append("G").append(defaultSong.getColor().getGreen()).toString();
            fontColor = (new StringBuilder()).append(fontColor).append("B").append(defaultSong.getColor().getBlue()).toString();
            songs.update("FontColor", fontColor);
            songs.write();
        }
    }

    public void windowClosed(WindowEvent e)
    {
        if(e.getSource() == this)
            System.exit(0);
    }

    public void windowIconified(WindowEvent windowevent)
    {
    }

    public void windowDeiconified(WindowEvent windowevent)
    {
    }

    public void windowActivated(WindowEvent windowevent)
    {
    }

    public void windowDeactivated(WindowEvent windowevent)
    {
    }

    public void actionPerformed(ActionEvent event)
    {
        if(event.getSource() == prefs) {
            preferences = new Preferences(out.getFrame().getX(), out.getFrame().getY(), out.getFrame().getWidth(), out.getFrame().getHeight(),out.getFont().getFamily());
            preferences.getApplied().addActionListener(this);
            preferences.getApplied().addActionListener(preferences);
            preferences.getClose().addActionListener(this);
        }
        if(preferences != null && event.getSource() == preferences.getApplied()) {
            //System.out.println("changing font "+preferences.getFontName());
            out.setFont(preferences.getFontName());
            if(preferences.getSpecific()) {
                out.changeLocation(preferences.getOutputX(), preferences.getOutputY());
                out.changeSize(preferences.getOutputWidth(), preferences.getOutputHeight());
                out.setSize(preferences.getOutputWidth(), preferences.getOutputHeight());
                fp.update("OutputX", (new StringBuilder()).append("").append(preferences.getOutputX()).toString());
                fp.update("OutputY", (new StringBuilder()).append("").append(preferences.getOutputY()).toString());
                fp.update("OutputWidth", (new StringBuilder()).append("").append(preferences.getOutputWidth()).toString());
                fp.update("OutputHeight", (new StringBuilder()).append("").append(preferences.getOutputHeight()).toString());
                fp.write();
            }
            //preferences.dispose();
        }
        if(preferences != null && event.getSource() == preferences.getClose()) {
            preferences.windowClosing(new WindowEvent(this, 0));
            preferences.dispose();
        }
        if(event.getSource() == findSong && (finder == null || !finder.isVisible()))
            finder = new Finder(getX()+100, getY()+100, 600, 450, sc.getSongs(), scheduler);
        if(event.getSource() == advancedSchedule) {
            as = new AdvancedSchedulerDialog(scheduler);
            as.setLocation(getX()+100, getY()+100);
        }
        if(event.getSource() == editSong) {
            if(sd1.getSong() != null&&sd1.isFocusOwner()) {
                editor = new SongEditor(sd1.getSong());
                editor.getFrame().addWindowListener(this);
                source = false;
                editor.getFrame().setLocation(getX()+100, getY()+100);
            }
            else if(sd0.getSong() !=null) {
                editor = new SongEditor(sd0.getSong());
                editor.getFrame().addWindowListener(this);
                source = source;
                editor.getFrame().setLocation(getX()+100, getY()+100);
            } 
        }
        if(event.getSource() == this.newSong)
        {
            
            editor = new SongEditor(sc);
            editor.getFrame().addWindowListener(this);
            editor.getFrame().setLocation(getX()+100, getY()+100);
        }
        if(event.getSource() == editDefault)
        {
            defaultEditor = new AdvancedScheduler(defaultSong, bible);
            defaultEditor.addWindowListener(this);
            defaultEditor.setLocation(getX()+100, getY()+100);
        }
        if(event.getSource() == clear)
            out.clear();
        if(event.getSource() == black) {
            
            out.black();
            //System.out.println("blacking out "+out.getName());
        }
        if(event.getSource() == t)
        {
            if(sc.isSongToAdd())
            {
                SongFile sf = sc.getSongAdding();
                scheduler.addSong(sf);
            }
            
            if(sc.isUpdated() && sc.getSelected() != null && sc.getSelected().getNumber() != sd0.getActive())
            {
                sd0.setSong(sc.getSelected());
                //sd0.getList().requestFocusInWindow();
                if(vf0 != null)
                    vf0.dispose();
                if(sc.getSelected().hasVideo())
                {
                    vf0 = new VideoFrame(out.getWidth(), out.getHeight());
                    vf0.loadVideo(sc.getSelected().getVideo());
                    vf0.setLocation(getX()+100, getY()+100);
                }
            } else if(scheduler.isUpdated() && scheduler.getActive() != null && scheduler.getActive() != sd0.getSong())
            {
                sd0.setSong(scheduler.getActive());
                //sd0.getList().requestFocusInWindow();
                if(vf0 != null)
                    vf0.dispose();
                if(scheduler.getActive().hasVideo())
                {
                    vf0 = new VideoFrame(out.getWidth(), out.getHeight());
                    vf0.loadVideo(scheduler.getActive().getVideo());
                    vf0.setLocation(getX()+100, getY()+100);
                }
            }
            if(sd0.isUpdated())
            {
                sd1.setSong(sd0.getSong());
                sd1.setActive(sd0.getActive());
                sd1.requestFocusInWindow();
                selected = selected.findNode(sd1);
                sd1.getList().requestFocusInWindow();
                if(vf0 != null)
                {
                    if(vf1 != null)
                        vf1.dispose();
                    vf1 = vf0;
                    vf1.setLocation(getX()+200, getY()+100);
                    vf0 = null;
                }
                if(sd0.getSong() == scheduler.getActive())
                {
                    scheduler.nextSong();
                    sd0.setSong(scheduler.getActive());
                    
                }
            }
            if(sd1.isUpdated())
            {
                //out.setClear(false);
                out.setLive(true);
                out.setSong(sd1.getSong());
                out.setVerse(sd1.getActive());
                black.setSelected(false);
                clear.setSelected(false);
                if(sd1.getSong().getNumber() == -1)
                    out.setText(" ");
                //out.setText(sd1.getSong().getVerse(sd1.getActive()));
                //out.setForeground(sd1.getSong().getColor());
                if(!out.isVisible()){
                    out.black();
                }    
                if(sd1.getSong().hasVideo())
                    sd1.setSong(sd1.getSong());
                
            } else if(out.getLive() && !out.isClear() && out.isVisible() && sd1.getSong().getNumber() != out.getID())
            {
                //String x[] = sd1.getSong().getVerse(sd1.getActive());
                if(sd1.getSong().hasVideo() && vf1 != null) {
                    vf1.updateBackground();
                    out.setBackground(vf1.getFrame());
                }
                out.setSong(sd1.getSong());
                //out.setText(x);
                out.setVerse(sd1.getActive());
            }
            if(sd1.getSong() != null && sd1.getSong().getNumber() == out.getID() && !out.isClear())
            {
                if(sd1.getSong().hasVideo() && vf1 != null) {
                    vf1.updateBackground();
                    out.setBackground(vf1.getFrame());
                }    
                if(sd1.getActive() != out.getVerse() && out.isVisible())
                {
                    //String x[] = sd1.getSong().getVerse(sd1.getActive());
                    //out.setText(x);
                    out.setVerse(sd1.getActive());
                }
            }
        }
        if(event.getSource() == open)
            scheduler.openSchedule();
        else
        if(event.getSource() == save)
            scheduler.saveSchedule();
        else
        if(event.getSource() == close)
            dispose();
    }

    public void setUndecorated(boolean b)
    {
        out.getFrame().setUndecorated(b);
    }

    public void setCapitalized(boolean b)
    {
        out.setCapitalized(b);
    }

    public static void main(String args[])
    {
        try
        {
            javax.swing.UIManager.LookAndFeelInfo looks[] = UIManager.getInstalledLookAndFeels();
            for(int i = 0; i < looks.length; i++)
                //System.out.println(looks[i].getClassName());
            UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        MainWindow mw = null;
        if(args != null && args.length > 0)
        {
            if(args[0].equals("-directory"))
            {
                String dir = (new StringBuilder()).append(args[1]).append("/").toString();
                mw = new MainWindow(800, 600, (new StringBuilder()).append(dir).append("MediaData.txt").toString(), (new StringBuilder()).append(dir).append("FramePositions.txt").toString());
            } else
            {
                for(int i = 0; i < args.length; i++)
                {
                    if(!args[i].equals("-media"))
                        continue;
                    for(int j = i; j < args.length; j++)
                        if(args[j].equals("-positions"))
                            mw = new MainWindow(800, 600, args[i + 1], args[j + 1]);

                }

            }
            if(mw == null)
                mw = new MainWindow();
            for(int i = 0; i < args.length; i++)
            {
                if(args[i].equals("-resolution"))
                    mw.setSize(Integer.parseInt(args[i + 1]), Integer.parseInt(args[i + 2]));
                if(args[i].equals("-schedule"))
                    mw.setSchedule(new File(args[i + 1]));
                if(args[i].equals("-decorate"))
                    mw.setUndecorated(false);
                if(args[i].equals("-capitalize"))
                    mw.setCapitalized(true);
            }

        } else
        {
            mw = new MainWindow();
        }
    }

    public void keyTyped(KeyEvent keyevent)
    {
    }

    public void keyPressed(KeyEvent ke) {
        int x = ke.getModifiers();
        int key = ke.getKeyCode();
       //System.out.println("key pressed "+x+" "+key);
        if(x==0 && key==39) {
            selected=selected.getNext();
            System.out.println(selected.getObject().requestFocusInWindow());
            try{
                Thread.sleep(60);
            } catch (Exception e) {
                e.printStackTrace();
            }
         //   System.out.println(selected.getObject());
        } else if(x==0 && key==37) {
            selected = selected.getPrevious();
            System.out.println(selected.getObject().requestFocusInWindow());
            try{
                Thread.sleep(60);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void keyReleased(KeyEvent keyevent) {
    }

    public void mouseClicked(MouseEvent mouseevent)
    {
    }

    public void mousePressed(MouseEvent e)
    {
        //requestFocus();
    }

    public void mouseReleased(MouseEvent mouseevent)
    {
    }

    public void mouseEntered(MouseEvent mouseevent)
    {
    }

    public void mouseExited(MouseEvent mouseevent)
    {
    }

}
